package com.holly.util;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import javax.crypto.SecretKey;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.Map;

/**
 * JWT 工具类 (Java 21)
 * 使用 jjwt 库实现 JWT 的创建、验证和解析
 */
public class JwtUtils {

    // 生成安全的 HMAC-SHA 密钥 (最小长度 256-bit)
    private static final SecretKey SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);
    // Token 有效期 (默认 1 小时)
    private static final long DEFAULT_EXPIRATION_MINUTES = 60;

    /**
     * 生成 JWT
     * @param claims 自定义声明
     * @param expirationMinutes 有效期（分钟）
     * @return JWT 字符串
     */
    public static String generateToken(Map<String, Object> claims, long expirationMinutes) {
        Instant now = Instant.now();
        Instant expiration = now.plus(expirationMinutes, ChronoUnit.MINUTES);

        return Jwts.builder()
                .setClaims(claims)                         // 添加自定义声明
                .setIssuedAt(Date.from(now))                // 签发时间
                .setExpiration(Date.from(expiration))       // 过期时间
                .signWith(SECRET_KEY)                       // 签名算法+密钥
                .compact();
    }

    /**
     * 生成 JWT（使用默认有效期）
     * @param claims 自定义声明
     * @return JWT 字符串
     */
    public static String generateToken(Map<String, Object> claims) {
        return generateToken(claims, DEFAULT_EXPIRATION_MINUTES);
    }

    /**
     * 验证并解析 JWT
     * @param token JWT 字符串
     * @return Claims 声明对象
     * @throws ExpiredJwtException Token过期异常
     * @throws io.jsonwebtoken.security.SignatureException 签名验证失败
     * @throws io.jsonwebtoken.MalformedJwtException 无效的JWT格式
     */
    public static Claims parseToken(String token) {
        return Jwts.parser()
                .setSigningKey(SECRET_KEY)  // 设置签名密钥
                .build()
                .parseClaimsJws(token)      // 解析并验证签名
                .getBody();
    }

    /**
     * 验证 Token 是否有效
     * @param token JWT 字符串
     * @return 是否有效
     */
    public static boolean validateToken(String token) {
        try {
            parseToken(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 刷新 Token
     * @param token 原JWT
     * @param addMinutes 延长的有效期（分钟）
     * @return 新的JWT
     */
    public static String refreshToken(String token, long addMinutes) {
        Claims claims = parseToken(token);
        return generateToken(claims, addMinutes);
    }
}